package com.neusoft.ch6;

import java.util.*;

import com.neusoft.ch6.demo1.Animal;
import com.neusoft.ch6.demo1.Lion;
import com.neusoft.ch6.demo1.Tiger;

/*
 * 课堂笔记：
 *    9.多态
 *      继承是子类继承了父类可以继承的属性和行为；
 *      多态是子类覆盖了父类同名的方法；（子类和父类的同名的行为不一样）【重写】
 *      多态也是父类指代子类的一种行为；【父类指代子类】
 *      
 *      多态体现在：
 *         方法的重写；（从子类的角度而言）
 *         用父类的变量指向子类的引用（从父类角度而言）【编程思想：面向父类的编程（面向接口的编程）】
 *         
 *    9.1方法重写
 *      课下作业：区别重写（override）和重载（overload）
 *      
 *      子类的同名方法覆盖父类的同名方法就是方法的重写（override）；   
 *      语法：
 *          1、子类和父类方法名相同
 *          2、返回值类型相同；
 *          3、父子类重写方法的参数列表相同
 *          4、子类重写方法的访问控制修饰符的范围>=父类方法的访问控制修饰符
 *          5、子类重写方法抛出的异常类的范围<=父类方法抛出异常类的范围； *          
 *          6、子类重写方法一般会使用  @Override 注解表明（即便不使用@Override也可以构成重写）
 *          
 *          在ide工具下可以使用右键--source--implements/override 自动生成需要重写的同名方法
 *          
 *      如果子类重写了父类的行为方法，则使用子类进行调用该方法时调用的是子类重写的方法；
 *      如果子类没有重写父类的行为方法，则子类进行调用该方法时调用的是继承自父类的方法；
 *      如果子类重写了父类的同名方法，还需要调用父类的同名的方法时，可以使用 super.同名方法名 进行调用；
 *   9.2父类指代子类
 *     用父类的变量指向子类的引用。
 *     语法：
 *        父类  变量名 = new 子类();【向上溯型】
 *     注意：
 *         1、=号左边是一个父类的类型；=右边是该父类的一个子类的实例对象
 *            变量类型是父类类型，但是在内存中其实一个子类实例对象；
 *         2、使用 变量名.方法 调用的是子类的方法；
 *         3、变量名.方法  只能调用子类中已经重写的父类的方法，子类新扩展的方法是无法调用到的；
 *         4、因为Object类是所有类的根类，所有所有的类（包括数组）都可以写成：
 *              Object obj = new 任何类();   
 *         5、可以将执行子类的父类变量通过强制类型转换的形式将其重新转换为子类类型；【向下溯型】  
 *           语法：
 *              子类  变量名  = (子类)父类类型变量；
 *           注意：
 *              只有指向子类的父类的变量才能重新转换为子类；
 *              普通的父类类型不能直接转换为子类类型；   
 *   9.3instanceof关键字
 *     类型判定操作符   
 *     父类执行子类的变量，instanceof操作符结果是true；
 *     该变量的所有的直接或间接父类的instanceof操作符判定结果都是true;
 *     
 *     
 *     
 *     
 *     
 */
public class TestOOPCh6 {

	public static void main(String[] args) {
		test03();

	}

	/**
	 * instanceof关键字：类型判定操作符
	 */
	private static void test04() {
		// 创建一个父类变量，指向子类的实例对象
		Animal an0 = new Tiger();
		// 判定an0是不是Object类型
		System.out.println("an0是不是Object类型:"+(an0 instanceof Object));
		// 判定an0是不是Animal类型
		System.out.println("an0是不是Animal类型:"+(an0 instanceof Animal));
		// 判定an0是不是Tiger类型
		System.out.println("an0是不是Tiger类型:"+(an0 instanceof Tiger));
		// 判定an0是不是Lion类型
		System.out.println("an0是不是Lion类型:"+(an0 instanceof Lion));
		
		System.out.println("============================");
		// 普通的父类类型变量
		Animal an1 = new Animal();
		// 判定an0是不是Object类型
		System.out.println("an1是不是Animal类型:"+(an1 instanceof Object));
		// 判定an0是不是Animal类型
		System.out.println("an1是不是Animal类型:"+(an1 instanceof Animal));
		// 判定an0是不是Tiger类型
		System.out.println("an1是不是Tiger类型:"+(an1 instanceof Tiger));
		// 判定an0是不是Lion类型
		System.out.println("an1是不是Lion类型:"+(an1 instanceof Lion));
		
	}

	/**
	 * 课堂练习： 有一群老虎和狮子，存储到数组中，输出这群老虎和狮子的饮食行为
	 */
	private static void test03() {
		Math.sqrt(1.2);
		Scanner sc =new Scanner(System.in);
		// 一群老虎
		Tiger tiger0 = new Tiger();
		Tiger tiger1 = new Tiger();
		Tiger tiger2 = new Tiger();
		// 一群狮子
		Lion lion0 = new Lion();
		Lion lion1 = new Lion();
		
		// 创建一个父类Anmal的数组，存储老虎和狮子
		Animal[] arrAnimal = new Animal[5]; 
		// 使用了多态：父类类型指代子类
		arrAnimal[0] = lion0;
		arrAnimal[1] = lion1;
		arrAnimal[2] = tiger0;
		arrAnimal[3] = tiger1;
		arrAnimal[4] = tiger2;
		
		printEating(arrAnimal);
	}
	
	/**
	 * 输出这群老虎和狮子的饮食行为
	 * @param arrAn
	 */
	private static void printEating(Animal[] arrAn) {
		for (Animal animal : arrAn) {
			if (animal instanceof Tiger) {
				System.out.print("我是Tiger：");
			} else {
				System.out.print("我是Lion：");
			}
			animal.eat();
		}
	}
	/**
	 * 父类指代子类的示例
	 */
	private static void test02() {
		// 创建一个父类变量，指向子类的实例对象
		Animal an0 = new Tiger();
		// 调用子类重写的父类的方法
		an0.walk();
		// 如果子类没有重写父类的方法，则调用子类继承到的父类的方法
		an0.sleep();
		// 无法调用子类新扩展的方法
		//an0.talk();
		
		System.out.println("=========向下溯型======");
		// 将父类animal类型的变量an0强制转换为子类tiger
		Tiger tiger0 = (Tiger) an0;
		// 就可以调用子类新增的行为方法了
		tiger0.walk();
		System.out.println("=========向下溯型22======");
		// 并不是所有的animal都可以向下溯型
		Animal an1= new Animal();
		// 向下溯型
		Tiger tiger1 = (Tiger) an1;
		// 调用子类的新增的方法
		tiger1.walk();
	}
	
	/**
	 * 方法重写的示例
	 */
	private static void test01() {
		// 创建一个子类Tiger实例对象
		Tiger tiger0 = new Tiger();
		// 调用子类重写方法
		tiger0.speak("tigerspeak"); // 该方法不是重写
		tiger0.walk(); // 重写
		tiger0.sleep(); // 继承
		tiger0.eat();
	}
}
